{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "ec6be4b3",
   "metadata": {},
   "outputs": [],
   "source": [
    "import  torch"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e9133201",
   "metadata": {},
   "source": [
    "张量表⽰⼀个由数值组成的数组，这个数组可能有多个维度。具有⼀个轴的张量对应数学上的向量（vector）；具有两个轴的张量对应数学上的矩阵（matrix）；具有两个轴以上的张量没有特殊的数学名称。\n",
    "\n",
    "⾸先，我们可以使⽤ arange 创建⼀个⾏向量 x。这个⾏向量包含以0开始的前12个整数，它们默认创建为整数。也可指定创建类型为浮点数。张量中的每个值都称为张量的 元素（element）。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "51b072ec",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = torch.arange(12)\n",
    "x"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3319675b",
   "metadata": {},
   "source": [
    "可以通过张量的shape属性来访问张量（沿每个轴的⻓度）的形状。也可以通过size来实现"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "7a898882",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "torch.Size([12])"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "a95c5e05",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "torch.Size([12])"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x.size()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9d50a0e0",
   "metadata": {},
   "source": [
    "如果只想知道张量中元素的总数，即形状的所有元素乘积，可以检查它的⼤⼩（size）。因为这⾥在处理的是⼀个向量，所以它的shape与它的size相同。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "032ba856",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "12"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x.numel()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b693505a",
   "metadata": {},
   "source": [
    "要想改变⼀个张量的形状⽽不改变元素数量和元素值，可以调⽤reshape函数。例如，可以把张量x从形状为\n",
    "（12,）的⾏向量转换为形状为（3,4）的矩阵。这个新的张量包含与转换前相同的值，但是它被看成⼀个3⾏4列\n",
    "的矩阵。要重点说明⼀下，虽然张量的形状发⽣了改变，但其元素值并没有变。注意，通过改变张量的形状，\n",
    "张量的⼤⼩不会改变。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "7f9857b4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[ 0,  1,  2,  3],\n",
       "        [ 4,  5,  6,  7],\n",
       "        [ 8,  9, 10, 11]])"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X = x.reshape(3,4)\n",
    "X"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "a6c662ac",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "torch.Size([3, 4])"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "f7df21f4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "torch.Size([3, 4])"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X.size()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "91aa20a4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "12"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X.numel()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "618db1e5",
   "metadata": {},
   "source": [
    "我们不需要通过⼿动指定每个维度来改变形状。也就是说，如果我们的⽬标形状是（⾼度,宽度），那么在\n",
    "知道宽度后，⾼度会被⾃动计算得出，不必我们⾃⼰做除法。在上⾯的例⼦中，为了获得⼀个3⾏的矩阵，\n",
    "我们⼿动指定了它有3⾏和4列。幸运的是，我们可以通过-1来调⽤此⾃动计算出维度的功能。即我们可以\n",
    "⽤x.reshape(-1,4)或x.reshape(3,-1)来取代x.reshape(3,4)。\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "7f9ea6fe",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[ 0,  1,  2,  3],\n",
       "        [ 4,  5,  6,  7],\n",
       "        [ 8,  9, 10, 11]])"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x.reshape(-1,4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "c671d51b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[ 0,  1,  2,  3],\n",
       "        [ 4,  5,  6,  7],\n",
       "        [ 8,  9, 10, 11]])"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x.reshape(3,-1)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "37c5e480",
   "metadata": {},
   "source": [
    "有时，我们希望使⽤全0、全1、其他常量，或者从特定分布中随机采样的数字来初始化矩阵。我们可以创建\n",
    "⼀个形状为（2,3,4）的张量，其中所有元素都设置为0，1。代码如下："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "3d34d713",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[[0., 0., 0., 0.],\n",
       "         [0., 0., 0., 0.],\n",
       "         [0., 0., 0., 0.]],\n",
       "\n",
       "        [[0., 0., 0., 0.],\n",
       "         [0., 0., 0., 0.],\n",
       "         [0., 0., 0., 0.]]])"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "torch.zeros((2,3,4))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "32734084",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[[1., 1., 1., 1.],\n",
       "         [1., 1., 1., 1.],\n",
       "         [1., 1., 1., 1.]],\n",
       "\n",
       "        [[1., 1., 1., 1.],\n",
       "         [1., 1., 1., 1.],\n",
       "         [1., 1., 1., 1.]]])"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "torch.ones((2,3,4))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "df985ea6",
   "metadata": {},
   "source": [
    "有时我们想通过从某个特定的概率分布中随机采样来得到张量中每个元素的值。例如，当我们构造数组来作\n",
    "为神经⽹络中的参数时，我们通常会随机初始化参数的值。以下代码创建⼀个形状为（3,4）的张量。其中的\n",
    "每个元素都从均值为0、标准差为1的标准⾼斯分布（正态分布）中随机采样。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "dc715fcd",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[ 0.0215, -0.7058,  0.9474, -0.6352],\n",
       "        [-0.1501,  0.4661, -1.2103,  0.3463],\n",
       "        [-0.1884, -0.2575,  0.9395,  0.8489]])"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "torch.randn(3,4)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "85becd3f",
   "metadata": {},
   "source": [
    "我们还可以通过提供包含数值的Python列表（或嵌套列表），来为所需张量中的每个元素赋予确定值。在这\n",
    "⾥，最外层的列表对应于轴0，内层的列表对应于轴1。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "cf559ba7",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[2, 1, 4, 3],\n",
       "        [1, 2, 3, 4],\n",
       "        [4, 3, 2, 1]])"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "torch.tensor([[2, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0f491855",
   "metadata": {},
   "source": [
    "对于任意具有相同形状的张量，常⻅的标准算术运算符（+、-、*、/和**）都可以被升级为按元素运算。我\n",
    "们可以在同⼀形状的任意两个张量上调⽤按元素操作。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "8c594ff2",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(tensor([3., 4., 5., 6.]),\n",
       " tensor([-1.,  0.,  1.,  2.]),\n",
       " tensor([2., 4., 6., 8.]),\n",
       " tensor([0.5000, 1.0000, 1.5000, 2.0000]),\n",
       " tensor([ 1.,  4.,  9., 16.]),\n",
       " tensor([ 2.7183,  7.3891, 20.0855, 54.5981]))"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import torch\n",
    "x = torch.tensor([1.0,2,3,4])\n",
    "y = torch.tensor([2,2,2,2])\n",
    "x + y, x - y ,x * y ,x / y, x ** y,torch.exp(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bf4f7fb8",
   "metadata": {},
   "source": [
    "以把多个张量连结（concatenate）在⼀起，把它们端对端地叠起来形成⼀个更⼤的张量。我们只需\n",
    "要提供张量列表，并给出沿哪个轴连结。下⾯的例⼦分别演⽰了当我们沿⾏（轴-0，形状的第⼀个元素）和按\n",
    "列（轴-1，形状的第⼆个元素）连结两个矩阵"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "cab4ac2b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(tensor([[ 0.,  1.,  2.,  3.],\n",
       "         [ 4.,  5.,  6.,  7.],\n",
       "         [ 8.,  9., 10., 11.],\n",
       "         [ 2.,  1.,  4.,  3.],\n",
       "         [ 1.,  2.,  3.,  4.],\n",
       "         [ 4.,  3.,  2.,  1.]]),\n",
       " tensor([[ 0.,  1.,  2.,  3.,  2.,  1.,  4.,  3.],\n",
       "         [ 4.,  5.,  6.,  7.,  1.,  2.,  3.,  4.],\n",
       "         [ 8.,  9., 10., 11.,  4.,  3.,  2.,  1.]]))"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X = torch.arange(12, dtype=torch.float32).reshape((3,4))\n",
    "Y = torch.tensor([[2.0, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])\n",
    "torch.cat((X, Y), dim=0), torch.cat((X, Y), dim=1)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ec9a3d3f",
   "metadata": {},
   "source": [
    "有时，我们想通过逻辑运算符构建⼆元张量。以X == Y为例：对于每个位置，如果X和Y在该位置相等，则新\n",
    "张量中相应项的值为1。这意味着逻辑语句X == Y在该位置处为真，否则该位置为0。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "690ba82d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[False,  True, False,  True],\n",
       "        [False, False, False, False],\n",
       "        [False, False, False, False]])"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X == Y"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a6c18b53",
   "metadata": {},
   "source": [
    "对张量中的所有元素进⾏求和，会产⽣⼀个单元素张量"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "9ca90a51",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor(66.)"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X.sum()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0d9a0446",
   "metadata": {},
   "source": [
    "### 2.1.3 广播机制\n",
    "在上⾯的部分中，我们看到了如何在相同形状的两个张量上执⾏按元素操作。在某些情况下，即使形状不同，\n",
    "我们仍然可以通过调⽤ ⼴播机制（broadcasting mechanism）来执⾏按元素操作。这种机制的⼯作⽅式如\n",
    "下：\n",
    "1. 通过适当复制元素来扩展⼀个或两个数组，以便在转换之后，两个张量具有相同的形状；\n",
    "2. 对⽣成的数组执⾏按元素操作。\n",
    "\n",
    "在⼤多数情况下，我们将沿着数组中⻓度为1的轴进⾏⼴播，如下例⼦"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "e126ab99",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(tensor([[0],\n",
       "         [1],\n",
       "         [2]]),\n",
       " tensor([[0, 1]]))"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = torch.arange(3).reshape((3,1))\n",
    "b = torch.arange(2).reshape((1,2))\n",
    "a,b"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6a69ff8e",
   "metadata": {},
   "source": [
    "由于a和b分别是3 × 1和1 × 2矩阵，如果让它们相加，它们的形状不匹配。我们将两个矩阵⼴播为⼀个更⼤\n",
    "的3 × 2矩阵，如下所⽰：矩阵a将复制列，矩阵b将复制⾏，然后再按元素相加。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "17e351df",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[0, 1],\n",
       "        [1, 2],\n",
       "        [2, 3]])"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a + b"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9e95b37f",
   "metadata": {},
   "source": [
    "### 2.1.4索引和切⽚  \n",
    "就像在任何其他Python数组中⼀样，张量中的元素可以通过索引访问。与任何Python数组⼀样：第⼀个元素\n",
    "的索引是0，最后⼀个元素索引是-1；可以指定范围以包含第⼀个元素和最后⼀个之前的元素。\n",
    "如下所⽰，我们可以⽤[-1]选择最后⼀个元素，可以⽤[1:3]选择第⼆个和第三个元素："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "ed656ee3",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(tensor([ 8.,  9., 10., 11.]),\n",
       " tensor([[ 4.,  5.,  6.,  7.],\n",
       "         [ 8.,  9., 10., 11.]]))"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X[-1], X[1:3]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "10745f8c",
   "metadata": {},
   "source": [
    "以通过指定索引来将元素写⼊矩阵"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "32c1a74d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[ 0.,  1.,  2.,  3.],\n",
       "        [ 4.,  5.,  9.,  7.],\n",
       "        [ 8.,  9., 10., 11.]])"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X[1, 2] = 9\n",
    "X"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f82f62fe",
   "metadata": {},
   "source": [
    "如果我们想为多个元素赋值相同的值，我们只需要索引所有元素，然后为它们赋值。例如，[0:2, :]访问\n",
    "第1⾏和第2⾏，其中“:”代表沿轴1（列）的所有元素。虽然我们讨论的是矩阵的索引，但这也适⽤于向量\n",
    "和超过2个维度的张量。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "4ce7fb57",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[12., 12., 12., 12.],\n",
       "        [12., 12., 12., 12.],\n",
       "        [ 8.,  9., 10., 11.]])"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X[0:2,:]=12\n",
    "X"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bcaf3e5f",
   "metadata": {},
   "source": [
    "### 2.1.5 节省内存\n",
    "运⾏⼀些操作可能会导致为新结果分配内存。例如，如果我们⽤Y = X + Y，我们将取消引⽤Y指向的张量，\n",
    "⽽是指向新分配的内存处的张量。\n",
    "在下⾯的例⼦中，我们⽤Python的id()函数演⽰了这⼀点，它给我们提供了内存中引⽤对象的确切地址。运\n",
    "⾏Y = Y + X后，我们会发现id(Y)指向另⼀个位置。这是因为Python⾸先计算Y + X，为结果分配新的内存，\n",
    "然后使Y指向内存中的这个新位置。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "8ab8f6bf",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "before = id(Y)\n",
    "Y = Y + X\n",
    "id(Y) == before"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "24841f99",
   "metadata": {},
   "source": [
    "频繁更换数组的存储位置这可能是不可取的，原因有两个：\n",
    "1. ⾸先，我们不想总是不必要地分配内存。在机器学习中，我们可能有数百兆的参数，并且在⼀秒内多次\n",
    "更新所有参数。通常情况下，我们希望原地执⾏这些更新；\n",
    "2. 如果我们不原地更新，其他引⽤仍然会指向旧的内存位置，这样我们的某些代码可能会⽆意中引⽤旧\n",
    "的参数。\n",
    "\n",
    "幸运的是，执⾏原地操作⾮常简单。我们可以使⽤切⽚表⽰法将操作的结果分配给先前分配的数组，例如Y[:]\n",
    "=expression。为了说明这⼀点，我们⾸先创建⼀个新的矩阵Z，其形状与另⼀个Y相同，使⽤zeros_like来\n",
    "分配⼀个全0的块。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "ef99d008",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "before id(Z): 2589730722256\n",
      "after id(Z): 2589730722256\n"
     ]
    }
   ],
   "source": [
    "Z = torch.zeros_like(Y)\n",
    "print('before id(Z):',id(Z))\n",
    "Z[:] = X + Y\n",
    "print('after id(Z):',id(Z))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d7bcab12",
   "metadata": {},
   "source": [
    "如果在后续计算中没有重复使⽤X，我们也可以使⽤X[:] = X + Y或X += Y来减少操作的内存开销。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "eb5c3b45",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "before = id(X)\n",
    "X += Y\n",
    "id(X) == before"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "efa03663",
   "metadata": {},
   "source": [
    "### 2.1.6 转换为其他Python对象\n",
    "将深度学习框架定义的张量转换为NumPy张量（ndarray）很容易，反之也同样容易。torch张量和numpy数\n",
    "组将共享它们的底层内存，就地操作更改⼀个张量也会同时更改另⼀个张量。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "671d353a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(numpy.ndarray, torch.Tensor)"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A = X.numpy()\n",
    "B = torch.tensor(A)\n",
    "type(A), type(B)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "371da169",
   "metadata": {},
   "source": [
    "要将⼤⼩为1的张量转换为Python标量，我们可以调⽤item函数或Python的内置函数。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "b40cea75",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(tensor([3.]), 3.0, 3.0, 3)"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = torch.tensor([3.0])\n",
    "a,a.item(), float(a), int(a)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "59ae658b",
   "metadata": {},
   "source": [
    "练习\n",
    "1. 运⾏本节中的代码。将本节中的条件语句X == Y更改为X < Y或X > Y，然后看看你可以得到什么样的\n",
    "张量。\n",
    "2. ⽤其他形状（例如三维张量）替换⼴播机制中按元素操作的两个张量。结果是否与预期相同？\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "cc2cf8a7",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(tensor([[False, False, False, False],\n",
       "         [False, False, False, False],\n",
       "         [False, False, False, False]]),\n",
       " tensor([[True, True, True, True],\n",
       "         [True, True, True, True],\n",
       "         [True, True, True, True]]))"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X < Y, X > Y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "3a9cac9e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(tensor([[[1.],\n",
       "          [1.]],\n",
       " \n",
       "         [[1.],\n",
       "          [1.]],\n",
       " \n",
       "         [[1.],\n",
       "          [1.]]]),\n",
       " tensor([[[1., 1., 1.]]]),\n",
       " tensor([[[2., 2., 2.],\n",
       "          [2., 2., 2.]],\n",
       " \n",
       "         [[2., 2., 2.],\n",
       "          [2., 2., 2.]],\n",
       " \n",
       "         [[2., 2., 2.],\n",
       "          [2., 2., 2.]]]))"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = torch.ones((3,2,1))\n",
    "b = torch.ones(1,1,3)\n",
    "a,b,a + b"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "ml",
   "language": "python",
   "name": "ml"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}